// 常量：复用代码有提示
const PENDING = 'pending' //等待
const FULFILLED = 'fulfilled'//成功
const REJECTED = 'rejected'//失败

class MyPromise {
  constructor (executor) {
    // 捕获
    try {
      executor(this.resolve, this.reject)
    } catch (e) {
      this.reject(e)
    }
  }
  // promise状态
  status = PENDING 
  // 成功之后得值
  value = undefined
  // 失败后的原因
  reason = undefined
  //成功回调
  successCallback = []
  //失败回调
  failCallback = []

  resolve = value => {
    // 如果状态不是等待阻止程序向下执行
    if(this.status !== PENDING) return
    // 将状态更改为成功
    this.status = FULFILLED
    // 保存成功之后的值
    this.value = value
    //判断成功回调是否存在 如果存在 调用
    while(this.successCallback.length) this.successCallback.shift()(this.value)

  }
  reject = reason => {
    // 如果状态不是等待阻止程序向下执行
    if(this.status !== PENDING) return
    // 将状态更改为失败
    this.status = REJECTED
    // 保存失败后的原因
    this.reason = reason
    //判断失败回调是否存在 如果存在 调用
    //shift是删除值
    while(this.failCallback.length) this.failCallback.shift()(this.reason)
  }
  then (successCallback, failCallback) {
    let promise2 = new MyPromise((resolve,reject) => {
      // 判断状态
      if (this.status === FULFILLED) {
        setTimeout(() =>{
          try{
            let x = successCallback(this.value) 
            resolvePromise(promise2, x, resolve, reject)
          }catch (e){
            this.reject(e)
          }       
        }, 0)
      } else if (this.status === REJECTED) {
        setTimeout(() =>{
          try{
              let x = failCallback(this.reason) 
              resolvePromise(promise2, x, resolve, reject)
          }catch (e){
          this.reject(e)
          }       
        }, 0)
      } else {
        //等待
        //将成功回调和失败回调存储起来
        this.successCallback.push(() => {
          setTimeout(() =>{
            try{
              let x = successCallback(this.value) 
              resolvePromise(promise2, x, resolve, reject)
            }catch (e){
              this.reject(e)
            }       
          }, 0)
        })
        this.failCallback.push(() => {
          setTimeout(() =>{
            try{
              let x = failCallback(this.reason) 
              resolvePromise(promise2, x, resolve, reject)
            }catch (e){
            this.reject(e)
            }       
          }, 0)
        })
      }
    })
    return promise2
  }
  static all (array) {
    let result = []
    let index = 0
    return new MyPromise((resolve, reject) => {
        function addData (key, value) {
            result[key] = value;
            index++;
            if(index === array.length) {
                resolve(result)
            }
        }
        for (let i = 0; i < array.length; i++) {
            //当前值
            let current = array[i];
            if(current instanceof MyPromise) {
                //promise对象
                current.then(value => addData(i, value),reason => reject(reason) )
            } else {
                //普通值
                assData(i, array[i])
            }
        }
    })
  }
  static resolve(value) {
    if(current instanceof MyPromise) return value;
    return new MyPromise(resolve => resolve(value))
  }
  finally (callback) {
    return this.then(value => {
        //callback()
        //return value
        return MyPromise.resolve(callback()).then(() => value);
    },reason => {
        //callback()
        //throw reason
        return MyPromise.resolve(callback()).then(() => {throw reason});  
    })
  }
  catch (failCallback) {
    return this.then(undefinded, failCallback)
  }
}

function resolvePromise(promise2, x, resolve, reject) {
  if( promise2 === x ) {
      return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
  }
  if (x instanceof MyPromise) {
      //promise对象
      // x.then(value => resolve(value), reason => reject(reason))
      x.then(resolve,reject)
  }else{
      //普通值
      resolve(x)
  }
}

module.exports = MyPromise